//
//  UITextField+LYAdd.m
//  LYDevelopKit
//
//  Created by 李阳 on 2018/5/25.
//

#import "UITextField+LYAdd.h"
#import <objc/runtime.h>
#import "LYUIMacros.h"

LYSYNTH_DUMMY_CLASS(UITextField_LYAdd)

@interface NSString (TextField_Regular)

/// 是否匹配 `regular` 正则表达式
- (BOOL)_matchesRegular:(NSString *)regular;

/// 是否包含emoji
- (BOOL)_containsEmoji;

/// 是否包含九宫格数字"➋➌➍➎➏➐➑➒"
- (BOOL)_containsSudokuNumber;

@end
@implementation NSString (TextField_Regular)

- (BOOL)_matchesRegular:(NSString *)regular
{
    if (regular.length < 1) return NO;
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regular];
    return [predicate evaluateWithObject:self];
}

- (BOOL)_containsEmoji
{
    if (!self.length)
    {
        return NO;
    }
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[^\\u0020-\\u007E\\u00A0-\\u00BE\\u2E80-\\uA4CF\\uF900-\\uFAFF\\uFE30-\\uFE4F\\uFF00-\\uFFEF\\u0080-\\u009F\\u2000-\\u201f\r\n]" options:NSRegularExpressionCaseInsensitive error:nil];
    return [regex firstMatchInString:self options:0 range:(NSRange){0, self.length}].range.length;
}

- (BOOL)_containsSudokuNumber
{
    if (!self.length)
    {
        return NO;
    }
    NSString *other = @"☻➋➌➍➎➏➐➑➒";     //九宫格的输入值
    return [other rangeOfString:self].location != NSNotFound;
}

@end

@interface LYTextRestrict : NSObject <UITextFieldDelegate>

@property (nonatomic, assign) NSUInteger maxLength;

@property (nonatomic, assign) LYRestrictType restrictType;

@property (nonatomic, copy)void(^breakMaxLengthBlock)(UITextField *);

@property (nonatomic, copy)void(^restrictBlock)(UITextField *);

@property (nonatomic, copy) void(^editingChangeBlock)(NSString *);

+ (instancetype)textRestrictWithRestrictType:(LYRestrictType)type;
- (BOOL)matchWithString:(NSString *)string;
@end


@implementation LYTextRestrict
+ (instancetype)textRestrictWithRestrictType:(LYRestrictType)type
{
    return [[LYTextRestrict alloc]initWithRestrictType:type];
}

- (instancetype)initWithRestrictType:(LYRestrictType)type {
    self = [super init];
    if (!self) return nil;
    _restrictType = type;
    _maxLength = NSUIntegerMax;
    return self;
}

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (!string.length)
    {
        return YES;
    }
    
    if ([self matchWithString:string])
    {
        !self.restrictBlock ?: self.restrictBlock(textField);
        return NO;
    }
    
    NSInteger existedLength = textField.text.length;
    NSInteger selectedLength = range.length;
    NSInteger replaceLength = string.length;
    
    if (existedLength - selectedLength + replaceLength > self.maxLength)
    {
        !self.breakMaxLengthBlock ?: self.breakMaxLengthBlock(textField);
        return NO;
    }
    
    return YES;
}

- (void)textDidChange:(UITextField *)textField
{
    !_editingChangeBlock ?: _editingChangeBlock(textField.text);
}

- (BOOL)matchWithString:(NSString *)string
{
    switch (self.restrictType)
    {
        case LYRestrictTypeFreedom:
            return YES;
            
        case LYRestrictTypeOnlyNumber:
            return [string _matchesRegular:@"^\\d$"];
            
        case LYRestrictTypeOnlyDecimal:
            return [string _matchesRegular:@"^[0-9.]$"];
            
        case LYRestrictTypeOnlyCharacter:
            return [string _matchesRegular:@"^[^[\\u4e00-\\u9fa5]]$"];
            
        case LYRestrictTypeOnlyEmoji:
            return !string._containsEmoji;
            
        case LYRestrictTypeExceptEmoji:
            return (string._containsEmoji && !string._containsSudokuNumber);
    }
    
    return YES;
}
@end




@interface UITextField (_Restrict)
/// 限制模型
@property (nonatomic, strong) LYTextRestrict *textRestrict;
@end
@implementation UITextField (_Restrict)
- (void)setTextRestrict:(LYTextRestrict *)textRestrict
{
    self.delegate = textRestrict;
    if (textRestrict)
    {
        [self addTarget:textRestrict
                 action:@selector(textDidChange:)
       forControlEvents:UIControlEventEditingChanged];
    }
    objc_setAssociatedObject(self, @selector(textRestrict), textRestrict, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (LYTextRestrict *)textRestrict
{
    return objc_getAssociatedObject(self, _cmd);
}
@end


@implementation UITextField (LYAdd)

#pragma mark - Public

- (void)setBlockOnBreakMaxLength:(void (^)(UITextField *))block
{
    if (!self.textRestrict)
    {
        return;
    }
    self.textRestrict.breakMaxLengthBlock = block;
}
- (void)setBlockOnBreakRestrict:(void (^)(UITextField *))block
{
    if (!self.textRestrict)
    {
        return;
    }
    self.textRestrict.restrictBlock = block;
}
- (void)setBlockOnEditingChanged:(void (^)(NSString *))block
{
    if (!self.textRestrict)
    {
        self.textRestrict = [LYTextRestrict textRestrictWithRestrictType:LYRestrictTypeFreedom];
    }
    self.textRestrict.editingChangeBlock = block;
}


#pragma mark - Properties

- (LYRestrictType)restrictType
{
    return self.textRestrict.restrictType;
}
- (void)setRestrictType:(LYRestrictType)restrictType
{
    if (self.textRestrict)
    {
        self.textRestrict.restrictType = restrictType;
        return;
    }
    LYTextRestrict *textRestrict = [LYTextRestrict textRestrictWithRestrictType:restrictType];
    if (self.maxTextLength)
    {
        textRestrict.maxLength = self.maxTextLength;
    }
    
    self.textRestrict = textRestrict;
}

- (NSUInteger)maxTextLength
{
    return self.textRestrict.maxLength;
}

- (void)setMaxTextLength:(NSUInteger)maxTextLength
{
    if (maxTextLength <= 0)
    {
        return;
    }
    
    if (self.textRestrict)
    {
        self.textRestrict.maxLength = maxTextLength;
        return;
    }
    
    LYTextRestrict *textRestrict = [LYTextRestrict textRestrictWithRestrictType:LYRestrictTypeFreedom];
    textRestrict.maxLength = maxTextLength;
    
    self.textRestrict = textRestrict;
}
@end


@implementation UITextField (Placeholder)

- (void)setPlaceholderFont:(UIFont *)font
{
    [self setValue:font forKeyPath:@"_placeholderLabel.font"];
}
- (UIFont *)placeholderFont
{
    return [self valueForKeyPath:@"_placeholderLabel.font"];
}
- (void)setPlaceholderColor:(UIColor *)color
{
    [self setValue:color forKeyPath:@"_placeholderLabel.textColor"];
}
- (UIColor *)placeholderColor
{
    return [self valueForKeyPath:@"_placeholderLabel.textColor"];
}

@end
